/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ru.miit.elearning.vtutor.check;

import ru.miit.elearning.vtutor.check.object.CheckObjectTypeHelper;
import java.util.logging.Level;
import java.util.logging.Logger;
import ru.miit.elearning.vtutor.data.CheckObject;
import ru.miit.elearning.vtutor.data.DataMiner;
import java.io.IOException;
import java.sql.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.net.ftp.FTPFile;
import org.json.JSONArray;
import org.json.JSONObject;
import ru.miit.elearning.vtutor.check.object.AbstractCheckObject;
import ru.miit.elearning.vtutor.ftp.FtpEntry;
import ru.miit.elearning.vtutor.ftp.FTPClientDecorator;
import ru.miit.elearning.vtutor.wsclient.VlApprovedLab;
import ru.miit.elearning.vtutor.wsclient.VlLab;
import ru.miit.elearning.vtutor.wsclient.VlStudent;

/**
 *
 * @author Cyclone
 */
public class ZOSChecker {
    protected static final int NO_NEED_TO_CHECK = -1;
    protected static final int PERCENT_APPROVED = -2;

    public ZOSChecker(int courseId, String FtpFullUrl) {
        this.courseId = courseId;
        this.ftpFullUrl = FtpFullUrl;
    }

    public String checkLabsByStudents(List<VlLab> labList, List<VlStudent> studentList, Set<VlApprovedLab> approvedSet) throws Exception {
//long zosCheckerFtpTime = 0
//        , s1 = 0, e1 = 0, s2 = 0, e2 = 0, s3 = 0, e3 = 0;

        String message = "";
        try {
            miner = new DataMiner();

            Date currentDate = new Date(System.currentTimeMillis());
            this.approvedSet = approvedSet;
            for (VlStudent student : studentList) {
                String home = student.getZOSHomeFolder();
//                System.out.println("home = " + home);
//
//                String zosHome = home;
//                if(zosHome.contains(";")) {
//                    zosHome = zosHome.split(";")[0];
//                }

                if(home != null && home.indexOf("/") == 0) {
                    getFtpClient().cd(home);
                } else {
                    getFtpClient().cd("//" + home);
                }
                
                String[] names = getFtpClient().listNames();
                if(names == null || names.length < 1) {
                    message += "  Студент "+student.getName()+": домашний каталог \""+student.getZOSHomeFolder()+"\" пуст.\n";

                    continue;
                }
                FTPFile[] files = getFtpClient().listFiles();
                Map<String, FtpEntry> entryMap = new HashMap<String, FtpEntry>();
                for (String name : names) {
                    try {
                        FtpEntry entry = new FtpEntry();
                        entry.setName(name);
                        for (FTPFile file : files) {
                            if (file != null) {
                                if (file.getName().equalsIgnoreCase(name)) {
                                    entry.setType(file.getType());
                                }
                            }
                        }
                        entryMap.put(name, entry);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                getFtpClient().setEntryMap(entryMap);

//                Iterator<String> it = entryMap.keySet().iterator();
//                while(it.hasNext()) {
//                    System.out.println(it.next());
//                }

                for (VlLab lab : labList) {
                    JSONObject jsonCheck = new JSONObject();
                    jsonCheck.put("labNumber", lab.getNumeral());
                    jsonCheck.put("studentId", student.getId());


                    CheckLabResult clr = checkLabByStudent(lab, student);
                    if (clr != null) {
                        if (clr.getPercent() != PERCENT_APPROVED) {
                            jsonCheck.put("checkObjects", clr.getDetails());
                            jsonCheck.put("percent", clr.getPercent());
                            miner.setFinishedByWork(student.getId(), this.courseId, lab.getNumeral(), clr.getPercent(), jsonCheck.toString(), currentDate);
                        } else {
                            jsonCheck.put("percent", PERCENT_APPROVED); // approved
                        }
                    }
                }

                getFtpClient().clearListMap();
            }

            //return detailJsonArray.toString().replace("},{", "},<br/>{");
            return message;
        } finally {
            if (ftpClient != null) {
                try {
                    ftpClient.close();
                } catch (IOException ex) {
                    Logger.getLogger(ZOSChecker.class.getName()).log(Level.SEVERE, null, ex);
                    ex.printStackTrace();
                }
            }
            if (miner != null) {
                miner.close();
            }
        }
    }

    private CheckLabResult checkLabByStudent(VlLab lab, VlStudent student) throws Exception {
        // System.out.println(getClass() + ".checkLabByStudent(): line 50");
        try {

            int studentId = student.getId();

            VlApprovedLab approvedLab = new VlApprovedLab();
            approvedLab.setStudentId(studentId);
            approvedLab.setLabNumber(lab.getNumeral());


            for (Iterator<VlApprovedLab> it = approvedSet.iterator(); it.hasNext();) {
                VlApprovedLab al = it.next();

                // if (approvedSet.contains(approvedLab)) { // DOESN'T WORK!
                if (((al.getLabNumber() == approvedLab.getLabNumber())
                        && (al.getStudentId() == approvedLab.getStudentId()))) {
                    // nothing to do with the lab
                    approvedSet.remove(al);
                    return new CheckLabResult(PERCENT_APPROVED, null);
                }
            }

            List<CheckObject> checkObjectList = miner.getCheckObjectList(courseId, lab.getNumeral());

            if (checkObjectList == null || checkObjectList.size() < 1) {
                // lab is not cheched
                return new CheckLabResult(NO_NEED_TO_CHECK, null);
            } // else

            CheckLabResult clr = new CheckLabResult();
            int total = checkObjectList.size();
            int checked = 0;

            JSONArray jsonCheckObjects = new JSONArray();

            for (CheckObject checkObject : checkObjectList) {
                AbstractCheckObject aco = CheckObjectTypeHelper.getCheckableInstance(checkObject);
                CheckObjectResult result = aco.check(student, getFtpClient());

                if (result.isChecked()) {
                    checked++;
                }

                jsonCheckObjects.put(result.getDetails());
            }

            clr.setDetails(jsonCheckObjects);

            int percent = 0;
            if (checked == total) {
                percent = 100;
            } else {
                percent = (int) (((float) checked / total) * 100);
            }
            // System.out.println("\tPercent = " + percent);
            clr.setPercent(percent);
            return clr;
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            System.err.println("Exception: " + e.getMessage());
            throw e;
        }
    }
    protected Set<VlApprovedLab> approvedSet;
    protected FTPClientDecorator ftpClient;
    protected String ftpFullUrl;
    protected int courseId;
    protected DataMiner miner;
//    protected JSONArray detailJsonArray;

    /**
     * Get the value of ftpClient
     *
     * @return the value of ftpClient
     */
    public FTPClientDecorator getFtpClient() throws IOException {
        if (ftpClient == null) {
            ftpClient = new FTPClientDecorator();
            //ftpClient.getFTPClient().setConnectTimeout(30000);
        }

        if (!ftpClient.isConnected()) {
            try {
                ftpClient.connect(ftpFullUrl);
            } catch (Exception e) {
                System.err.println("Ошибка подключения к FTP серверу");
                e.printStackTrace();
                if (e instanceof IOException) {
                    throw (IOException) e;
                }
            }
        }

        return ftpClient;
    }
}
